<?php

namespace App\Exceptions;

use Exception;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
use Illuminate\Session\TokenMismatchException;
use Illuminate\Support\Facades\Log;
use Illuminate\Validation\UnauthorizedException;
use Illuminate\Validation\ValidationException;
use Symfony\Component\HttpKernel\Exception\HttpException;
use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException;

class Handler extends ExceptionHandler
{
    /**
     * A list of the exception types that are not reported.
     *
     * @var array
     */
    protected $dontReport = [
        //
    ];

    /**
     * A list of the inputs that are never flashed for validation exceptions.
     *
     * @var array
     */
    protected $dontFlash = [
        'password',
        'password_confirmation',
    ];

    /**
     * Report or log an exception.
     *
     * @param  \Exception  $exception
     * @return void
     */
    public function report(Exception $exception)
    {
        Log::error($exception->getMessage(),['resp'=>json_encode(['request_id'=>REQUESTID,'previous'=>$exception->getPrevious()])]);
        if (!app()->isLocal() && !isset($GLOBALS['error'])) {
            logError('handler error as follows：');
            logError($exception);
            $GLOBALS['error'] = 1;
            // 验证规则不通过
            if ($exception instanceof ValidationException) {
                $GLOBALS['error_handle'] = $this->_responseHttpError(['status_code' => 400,'message' => current($exception->errors())[0]]);
            } elseif ($exception instanceof UnauthorizedException) {
                // 权限不足
                $GLOBALS['error_handle'] = $this->_responseHttpError(['status_code' => 400, 'message' => '鉴权失败']);
            } elseif ($exception instanceof UnauthorizedHttpException) {
                // 授权失败
                $GLOBALS['error_handle'] = $this->_responseHttpError(['status_code' => 401, 'message' => '未鉴权']);
            } elseif ($exception instanceof NotFoundHttpException) {
                // 请求方法不存在
                throw new HttpException('404', '路由不存在');
            } elseif ($exception instanceof MethodNotAllowedHttpException) {
                // 请求方法不存在
                throw new HttpException('405', '访问方法不存在');
            } elseif ($exception instanceof ModelNotFoundException) {
                // 查询数据不存在
                $GLOBALS['error_handle'] = $this->_responseHttpError(['status_code' => 404, 'message' => '查询数据不存在']);
            } elseif ($exception instanceof \PDOException) {
                // 数据库连接失败
                $GLOBALS['error_handle'] = $this->_responseHttpError(['status_code' => 500, 'message' => '数据库连接失败']);
            } elseif ($exception instanceof CustomException) {
                // 抛出自定义错误
                $GLOBALS['error_handle'] = $this->_responseHttpError(['status_code' => $this->_getErrorCode($exception), 'message' => $exception->getMessage()]);
            } elseif ($exception instanceof TokenMismatchException){
                $GLOBALS['error_handle'] = $this->_responseHttpError(['status_code' => 403, 'message' => '鉴权失败，请登录']);
            }else {
                // 捕获其它错误 $exception instanceof HttpException || $exception instanceof Exception
                $GLOBALS['error_handle'] = $this->_responseHttpError(['status_code' => 500, 'message' => $exception->getMessage()]);
            }
        }
        $origin = isset($_SERVER['HTTP_ORIGIN']) ? $_SERVER['HTTP_ORIGIN'] : 'http://annual.gengyong.com.cn';
        header('Content-Type:application/json; charset=utf-8');
        header("Access-Control-Allow-Origin:".$origin);
        header("Access-Control-Allow-Credentials: true ");
        header("request_id: ".REQUESTID);
        header('Access-Control-Allow-Headers:*');
        header('Access-Control-Allow-Methods:*');
        header('Access-Control-Expose-Headers: *');
//        header('Content-Type:application/json: charset=utf-8');
//        header('Access-Control-Allow-Origin: *');
//        header('Access-Control-Allow-Headers: *');
//        header('Access-Control-Expose-Headers: *');
//        header('Access-Control-Allow-Methods:GET, POST, PATCH, PUT, OPTIONS');
//        header('Access-Control-Allow-Credentials: true');
//        header("request_id",REQUESTID);
        parent::report($exception);
    }

    /**
     * Render an exception into an HTTP response.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Exception  $exception
     * @return \Illuminate\Http\Response
     */
    public function render($request, Exception $exception)
    {
        if (app()->isLocal()) {
            dd($exception);
            return parent::render($request, $exception);
        } else{
            return response()->json(['msg' => $exception->getMessage(),'code' => ($exception->getStatusCode() ?? $exception->getCode())]);
        }
    }

    private function _getErrorCode($exception)
    {
        try {
            $errorCode = $exception->getCode();
        } catch (\Exception $e) {
            $errorCode = 500;
        }
//        if ($errorCode >= 600 || $errorCode <= 0) {
//            $errorCode = 500;
//        }

        return $errorCode;
    }

//    private function _responseResourceError($data)
//    {
//
//        throw new CustomException($data['message'], $data['errors']);
//    }

    private function _responseHttpError($data)
    {
        throw new HttpException($data['status_code'], $data['message']);
    }
}
